package com.istock.union.controller;

import java.io.IOException;
import java.util.Date;
import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import com.istock.base.enumration.Enums;
import com.istock.union.user.client.SSOClientUtils;
import com.istock.union.user.model.LoginforInfo;
import com.istock.union.user.model.SSOUser;
import com.istock.union.user.model.TenantInfo;
import com.istock.union.user.security.InnerTokenService;
import com.istock.union.user.service.AschTaskService;
import com.istock.union.user.service.TenantInfoService;
import com.istock.union.user.utils.WebCommonUtils;

import eu.bitwalker.useragentutils.UserAgent;

@Controller
@RequestMapping("pre")
public class PreLoginController {

	@Value("${sso.url.login}")
	private String loginUrl;
	
	@Value("${sso.url.success}")
	private String loginSuccessUrl;
	
	@Value("${sso.token.name:logintoken}")
	private String tokenName;
	
	@Value("${sso.token.storeType:cookie}")
	private String tokenStoreType;
	
	@Autowired
	private InnerTokenService tokenService;
	
	@Autowired
	private TenantInfoService tenantInfoService;
	@Autowired
	private AschTaskService aschTaskService;
	
	@Value("${sso.login.verifyCount:3}")
	private Integer overVerifyCount;
	
	@Value("${sso.url.fromUrl:false}")
	private boolean fromUrlEnable = false;
	
	private Logger logger = LoggerFactory.getLogger(getClass());
	/**控制多iframe显示的后台页面,在最外层的window进行展示登录页面
	 * 如果是正常的退出,也是跳转到toLogin,在最外层的window渲染登录页面
	 * 如果是非正常的退出,比如在打开iframe页面的内部出现,是需要toLogin在浏览器上进行window的切换
	 * 
	 * 注意toLogin的时候,需要对fromurl进行传递,否则登录页面在登录完成以后,就不能顺利的打开后面的页面
	 * @return
	 */
	@RequestMapping("toLogin")
	public String toLogin(ModelMap model,String fromUrl , HttpServletRequest request){
		String targetUrl = WebCommonUtils.generateTargetUrl(request.getContextPath(), "pre/preLogin");
		if(StringUtils.isNotBlank(fromUrl)){
			targetUrl = WebCommonUtils.generateFromUrl(targetUrl, "fromUrl", fromUrl);
		}
		return toRedirect(model , targetUrl);
	}
	
	@RequestMapping("redirectPage")
	public String redirectPage(ModelMap model , String targetUrl , String setTokenFlag , String clearTokenFlag , String type) {
		if(StringUtils.isNotBlank(setTokenFlag)) {
			model.put("set", true);
		}
		if(StringUtils.isNotBlank(clearTokenFlag)) {
			model.put("clear", true);
		}
		if(StringUtils.isNotBlank(type)) {
			model.put("type", type);
		}
		
		return toRedirect(model , targetUrl);
	}
	
	private String toRedirect(ModelMap model , String targetUrl){
		if(StringUtils.isNotBlank(targetUrl)) {
			model.put("targetUrl", targetUrl);
		}
		return "login/redirect";
	}
	
	/**展示登录首页
	 * 
	 * 登录的输入信息以iframe的方式展示,在iframe的外面,都是应用程序自己的事情,和sso无关
	 * 
	 * 不是默认就展示,如果用户被封了,展示小黑屋页面,不允许用户操作
	 * @param model
	 * @param fromUrl
	 * @return
	 */
	@RequestMapping("preLogin")
	public String preLogin(ModelMap model,String fromUrl){
		if(StringUtils.isNotBlank(fromUrl)){
			model.put("fromUrl", fromUrl);
		}
		return "login/login";
	}
	
	/**展示登录的iframe信息
	 * 传递fromUrl
	 * 
	 * 在这个controller内部,需要对登录信息进行判断
	 * 如果已经包含登录信息的请求,将不会展示登录输入框,而是直接进行跳转到登录成功后的页面
	 * 
	 * 如果已经包含token,而且token是有效的
	 * 在这个页面,会给fromurl生成ticket
	 * 
	 * @param model
	 * @param fromUrl
	 * @return
	 */
	@RequestMapping("showLogin")
	public String showLogin(ModelMap model , HttpServletRequest request , HttpServletResponse response,String fromUrl){
		if(StringUtils.isNotBlank(fromUrl)){
			model.put("fromUrl", fromUrl);
		}
		HttpSession session = request.getSession(true);
		Integer loginTime = NumberUtils.toInt(session.getAttribute("loginTime")+"", 0);
		logger.debug("showLogin  -====== loginTime:{} , overVerifyCount:{}" , loginTime , overVerifyCount);
		if(loginTime >= overVerifyCount){
			model.put("needVerify", true);
		}
		
		//在展示登录输入框之前,判断当前的请求是否包含登录信息
		String token = WebCommonUtils.findToken(request , tokenName);
		logger.debug("find the token:[{}] in the request" , token);
		
		if(StringUtils.isNotBlank(token)){
			SSOUser ssoUser = tokenService.verify(token);
			if(ssoUser != null){
				logger.debug("verify token success , the user:{}" , ssoUser);
				SSOClientUtils.getInstance().setCurrent(token);
				
				//如果是SSO的showLogin,需要判断fromUrl是否在自己的登录授权下面,如果是,则需要通过token给fromUrl生成ticket进行跳转,而不是生成登录页面
				/*String targetDomain = request.getServerName();
				if(StringUtils.isBlank(targetDomain)) {
					targetDomain = request.getServerName(); 
				}*/
				model.put("type", "post");
				if(fromUrlEnable && StringUtils.isNotBlank(fromUrl)) {
					return toRedirect(model, WebCommonUtils.generateTargetUrl(request.getContextPath(), fromUrl));
				}
				return toRedirect(model, WebCommonUtils.generateTargetUrl(request.getContextPath(), loginSuccessUrl));
			}
		}
		
			List<TenantInfo> tenantList = tenantInfoService.findAllTenantList();
			model.put("tenantList", tenantList);
		return "login/loginFrame";
	}
	
	/**
	 * sso的登出
	 * 所有的登出必须交给sso的登出
	 * 由sso负责调用外部的登出逻辑
	 * @param request
	 * @return
	 */
	@RequestMapping("logout")
	public String logout(ModelMap model ,HttpServletRequest request, HttpServletResponse response){
		String token = WebCommonUtils.findToken(request , tokenName);
		logger.debug("find the token:[{}] in the request" , token);
		LoginforInfo loginforInfo = new LoginforInfo();
		UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
		loginforInfo.setBrowser(userAgent.getBrowser().getName());
		loginforInfo.setIpaddr(WebCommonUtils.findRemoteAddr(request));
//		loginforInfo.setLoginLocation(loginLocation);
		
		loginforInfo.setLogType(Enums.getInstance().getEnumsValueByCode("LOG_TYPE", "LOG_TYPE_OUT"));
		loginforInfo.setOs(userAgent.getOperatingSystem().getName());
		
		if(StringUtils.isNotBlank(token)){
			SSOUser ssoUser = tokenService.verify(token);
			if(ssoUser != null){
				logger.debug("verify token success , the user:{}" , ssoUser);
				loginforInfo.setLoginName(ssoUser.getLoginName());
				loginforInfo.setResult("登出成功");
				loginforInfo.setTenantCode(ssoUser.getTenantNo());
				loginforInfo.setOperTime(new Date());
				
				SSOClientUtils.getInstance().setCurrent(token);
				//清空本地的token,以及所有的ticket
				tokenService.invalidToken(token);
				
				aschTaskService.loginInfoRecord(loginforInfo);
			}
		}
		
		
		
		//将token从浏览器清除
		if(tokenStoreType.equalsIgnoreCase("cookie")){
			for(Cookie cookie : request.getCookies()){
				WebCommonUtils.removeCookie(response, cookie.getName());
			}
			
		}else{
			model.put("clear", true);
		}
		return toRedirect(model, WebCommonUtils.generateTargetUrl(request.getContextPath(), loginUrl));
	}
	
	@RequestMapping("testFilePre")
	public String testFilePre() {
		return "test/login";
	}
	
	@RequestMapping("testFile")
	public String testFile( String aaa ,String bbb, MultipartFile file) {
		try {
			byte[] b = file.getBytes();
			String str = new String(b);
			System.out.println(str);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "";
	}
	
}
